home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Devices and Hardware / ADB / ControlKeyPatch / ControlKeyPatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  6.7 KB  |  209 lines  |  [TEXT/MPS ]

  1. /*    File:        ControlKeyPatch.c
  2.     
  3.     Description: 
  4.              routines for patching the ADB manager to simulate the control
  5.             key being held down.  This file contains routines for installing,
  6.             removing and calling the control key patch.  Client code
  7.             can link with this file and place the patch resource in their
  8.             resource fork.
  9.  
  10.     Author:    John Montbriand
  11.  
  12.     Copyright: 
  13.             Copyright © 1999 by Apple Computer, Inc.
  14.             All rights reserved worldwide.
  15.     
  16.     Disclaimer:
  17.             You may incorporate this sample code into your applications without
  18.             restriction, though the sample code has been provided "AS IS" and the
  19.             responsibility for its operation is 100% yours.  However, what you are
  20.             not permitted to do is to redistribute the source as "DSC Sample Code"
  21.             after having made changes. If you're going to re-distribute the source,
  22.             we require that you make it clear in the source that the code was
  23.             descended from Apple Sample Code, but that you've made changes.
  24.     
  25.     Change History (most recent first):
  26.             27/8/99 created by John Montbriand
  27. */
  28.  
  29.  
  30. #include "ControlKeyPatch.h"
  31. #include <Resources.h>
  32. #include <Memory.h>
  33. #include <Errors.h>
  34.  
  35.  
  36. OSErr NewControlKeyPatch(Boolean inSysHeap, ControlKeyPatchPtr *patch) {
  37.     ADBSetInfoBlock siBlock;
  38.     ControlKeyPatchPtr patchResult;
  39.     ControlKeyPatchSegment **patchSegData, *patchSegment;
  40.     long patchsize, adbCount, i;
  41.     KeyCmdCallUPP upHook, downHook;
  42.     Boolean patchInstalled, sysheapActive;
  43.     THz savedZone;
  44.     OSErr err;
  45.     
  46.         /* set up locals to a known state */
  47.     patchSegData = NULL;
  48.     patchResult = NULL;
  49.     patchSegment = NULL;
  50.     upHook = downHook = NULL;
  51.     patchInstalled = false;
  52.     sysheapActive = false;
  53.  
  54.         /* get the patch resource */
  55.     patchSegData = (ControlKeyPatchSegment **) GetResource('PROC', 128);
  56.     if (patchSegData == NULL) { err = resNotFound; goto bail; }
  57.     patchsize = GetHandleSize((Handle) patchSegData);
  58.     
  59.         /* set the memory manager heap to the target */
  60.     if (inSysHeap) {
  61.         savedZone = GetZone();
  62.         SetZone(SystemZone());
  63.         sysheapActive = true;
  64.     }
  65.     
  66.         /* allocate our state variables */
  67.     patchResult = (ControlKeyPatchPtr) NewPtrClear(sizeof(ControlKeyPatchVars));
  68.     if (patchResult == NULL) { err = memFullErr; goto bail; }
  69.     patchResult->downflag = 0;
  70.     patchResult->systemPatch = inSysHeap;
  71.  
  72.         /* allocate the patch segment's storage */
  73.     patchSegment = (ControlKeyPatchSegment *) NewPtr(patchsize);
  74.     if (patchSegment == NULL) { err = memFullErr; goto bail; }
  75.     BlockMove(*patchSegData, patchSegment, patchsize);
  76.     patchResult->patchSegment = patchSegment;    
  77.         
  78.         /* save pointers/routine descriptors for the callbacks */
  79.     downHook = NewControlKeyCommandUPP(&patchSegment->downbranch);
  80.     upHook = NewControlKeyCommandUPP(&patchSegment->upbranch);
  81.     patchResult->SetKeyDownHook = downHook;
  82.     patchResult->SetKeyUpHook = upHook;
  83.     
  84.         /* find the first keyboard and patch its service routine */
  85.     adbCount = CountADBs();
  86.     for ( i = 1; i <= adbCount; i++) {
  87.         ADBDataBlock adbInfo;
  88.         ADBAddress adbAddress;
  89.             /* get the i'th ADB entry */
  90.         adbAddress = GetIndADB(&adbInfo, i);
  91.         if (adbAddress < 0) continue; /* no device in that entry */
  92.             /* only process keyboards */
  93.         if (adbInfo.origADBAddr == 2) {
  94.                 /* save the command  address + talk code */
  95.             patchResult->command = ((adbAddress<<4) | 0xC);
  96.             
  97.                 /* the adb address */
  98.             patchResult->adbAddress = adbAddress;
  99.  
  100.                 /* save the service routines in the patch data */
  101.             patchResult->originaljump = (long) adbInfo.dbServiceRtPtr;
  102.             patchResult->originaldata = (long) adbInfo.dbDataAreaAddr;
  103.  
  104.                 /* replace the device's service routine to call our patch */
  105.             siBlock.siService = (ADBServiceRoutineUPP) patchSegment;
  106.             siBlock.siDataAreaAddr = (Ptr) patchResult;
  107.             SetADBInfo(&siBlock, adbAddress);
  108.             
  109.                 /* exit */
  110.             patchInstalled = true;
  111.             break;
  112.         }
  113.     }
  114.     if ( ! patchInstalled) { err = kErrNoKeyboardFound; goto bail; }
  115.         /* restore the correct heap zone */
  116.     if (sysheapActive) SetZone(savedZone);
  117.         /* release the patch resource */
  118.     ReleaseResource((Handle) patchSegData);
  119.         /* return our patch state variables */
  120.     *patch = patchResult;
  121.     return noErr;
  122.     
  123. bail:    
  124.         /* restore the service routine, if it was set */
  125.     if (patchInstalled) {
  126.         siBlock.siService = (ADBServiceRoutineUPP) patchResult->originaljump;
  127.         siBlock.siDataAreaAddr = (Ptr) patchResult->originaldata;
  128.         SetADBInfo(&siBlock, patchResult->adbAddress);
  129.     }
  130.         /* deallocate storage as necessary */
  131.     if (patchSegment != NULL) DisposePtr((Ptr) patchSegment);
  132.     if (patchResult != NULL) DisposePtr((Ptr) patchResult);
  133.     if (upHook != NULL) DisposeControlKeyCommandUPP(upHook);
  134.     if (downHook != NULL) DisposeControlKeyCommandUPP(downHook);
  135.         /* restore the correct heap zone */
  136.     if (sysheapActive) SetZone(savedZone);
  137.         /* release the patch resource */
  138.     if (patchSegData != NULL) ReleaseResource((Handle) patchSegData);
  139.     return err;
  140. }
  141.  
  142. void DisposeControlKeyPatch(ControlKeyPatchPtr patch) {
  143.     ADBSetInfoBlock siBlock;
  144.         /* make sure the key is up */
  145.     CallControlKeyCommandUPP(patch->SetKeyUpHook, patch);
  146.         /* restore the original service routine */
  147.     siBlock.siService = (ADBServiceRoutineUPP) patch->originaljump;
  148.     siBlock.siDataAreaAddr = (Ptr) patch->originaldata;
  149.     SetADBInfo(&siBlock, patch->adbAddress);
  150.         /*release any routine descriptors */
  151.     DisposeControlKeyCommandUPP(patch->SetKeyDownHook);
  152.     DisposeControlKeyCommandUPP(patch->SetKeyUpHook);
  153.         /* dispose of the remaining storage */
  154.     DisposePtr((Ptr) patch->patchSegment);
  155.     DisposePtr((Ptr) patch);
  156. }
  157.  
  158.  
  159. OSErr ControlKeyPatchReInstall(ControlKeyPatchPtr patch) {
  160.     long adbCount, i;
  161.     Boolean patchInstalled;
  162.     
  163.         /* set up locals */
  164.     patchInstalled = false;
  165.  
  166.         /* find the first keyboard and patch its service routine */
  167.     adbCount = CountADBs();
  168.     for ( i = 1; i <= adbCount; i++) {
  169.         ADBDataBlock adbInfo;
  170.         ADBAddress adbAddress;
  171.             /* get the i'th ADB entry */
  172.         adbAddress = GetIndADB(&adbInfo, i);
  173.         if (adbAddress < 0) continue; /* no device in that entry */
  174.             /* only process keyboards */
  175.         if (adbInfo.origADBAddr == 2) {
  176.             ADBSetInfoBlock siBlock;
  177.                 /* save the command  address + talk code */
  178.             patch->command = ((adbAddress<<4) | 0xC);
  179.             
  180.                 /* the adb address */
  181.             patch->adbAddress = adbAddress;
  182.  
  183.                 /* save the service routines in the patch data */
  184.             patch->originaljump = (long) adbInfo.dbServiceRtPtr;
  185.             patch->originaldata = (long) adbInfo.dbDataAreaAddr;
  186.  
  187.                 /* replace the device's service routine to call our patch */
  188.             siBlock.siService = (ADBServiceRoutineUPP) patch->patchSegment;
  189.             siBlock.siDataAreaAddr = (Ptr) patch;
  190.             SetADBInfo(&siBlock, adbAddress);
  191.             
  192.                 /* exit */
  193.             patchInstalled = true;
  194.             break;
  195.         }
  196.     }
  197.     if ( ! patchInstalled)
  198.         return kErrNoKeyboardFound;
  199.     else return noErr;
  200. }
  201.  
  202. void SetControlKeyDown(ControlKeyPatchPtr patch) {
  203.     CallControlKeyCommandUPP(patch->SetKeyDownHook, patch);
  204. }
  205.  
  206. void SetControlKeyUp(ControlKeyPatchPtr patch) {
  207.     CallControlKeyCommandUPP(patch->SetKeyUpHook, patch);
  208. }
  209.